package com.free.mini.common.log;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;

import com.alibaba.fastjson.serializer.ValueFilter;

import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;

/**
 *
 */
@Slf4j
public class DataMaskFilter implements ValueFilter {

    public static DataMaskFilter instance() {
        return new DataMaskFilter();
    }

    /**
     * 正则表达式
     */
    private static final Map<Pattern, String> sensitiveDataPatternMap = new ConcurrentHashMap<>();
    /**
     * 敏感词关键字
     */
    private static final CopyOnWriteArrayList<String> keyWords = new CopyOnWriteArrayList<>();
    /**
     * 类型关键字集合
     */
    private static final Map<String, List<String>> descriptionKeyWordsMap = new ConcurrentHashMap<>();

    /**
     * 关键字与替换规则映射
     */
    private static final Map<String, Map<String, String>> keyWordToPatternInfoMap = new ConcurrentHashMap<>();

    @Override
    public Object process(Object object, String name, Object value) {
        for (DataMaskRuleEnum rule : DataMaskRuleEnum.values()) {
            List<String> fields = descriptionKeyWordsMap.get(rule.description);
            if (fields.contains(name.toUpperCase())) {
                value = value.toString().replaceAll(rule.regular, rule.result);
            }
        }
        return value;
    }

    public static String deSensitiveData(String key, String msg) {
        if (CollectionUtil.isEmpty(sensitiveDataPatternMap)) {
            initData();
        }

        boolean singleDeal = false;
        if (StringUtils.isNotBlank(key) && key.contains(":")) {
            String[] split = key.split(":");
            String keyInfo = split[0];
            String keyWord = Strings.EMPTY;
            if (StringUtils.isNotBlank(keyInfo)) {
                if (keyInfo.contains(" ")) {
                    String[] strings = keyInfo.split(" ");
                    keyWord = strings[strings.length - 1];
                } else {
                    keyWord = keyInfo;
                }
                if (StringUtils.isNotBlank(keyWord) && keyWords.contains(keyWord)) {
                    Map<String, String> patternInfoMap = keyWordToPatternInfoMap.get(keyWord);
                    if (CollectionUtil.isNotEmpty(patternInfoMap)) {
                        msg = msg.replaceAll(patternInfoMap.get("regular"), patternInfoMap.get("result"));
                        singleDeal = true;
                    }
                }
            }

        }

        if (!singleDeal) {
            for (Map.Entry<Pattern, String> patternStringEntry : sensitiveDataPatternMap.entrySet()) {
                Pattern pattern = patternStringEntry.getKey();
                String value = patternStringEntry.getValue();
                msg = pattern.matcher(msg).replaceAll(value);
            }
        }
        return msg;
    }

    private static synchronized void initData() {
        for (DataMaskRuleEnum rule : DataMaskRuleEnum.values()) {
            Pattern pattern = Pattern.compile(rule.regular);
            sensitiveDataPatternMap.put(pattern, rule.result);
            String fieldNames = rule.fieldName;
            String[] split = fieldNames.split("\\|");

            descriptionKeyWordsMap.put(rule.description, Arrays.asList(split));

            for (String field : split) {
                if (!keyWords.contains(field)) {
                    keyWords.add(field);
                    keyWords.add(field.toLowerCase());
                    keyWords.add(field.toUpperCase());

                    Map<String, String> patternInfoMap = new HashMap<>();
                    patternInfoMap.put("regular", rule.regular);
                    patternInfoMap.put("result", rule.result);

                    keyWordToPatternInfoMap.put(field, patternInfoMap);
                    keyWordToPatternInfoMap.put(field.toUpperCase(), patternInfoMap);
                    keyWordToPatternInfoMap.put(field.toLowerCase(), patternInfoMap);

                }
            }

        }
    }


    public static boolean containKeyWord(String message) {
        if (CollectionUtil.isEmpty(keyWords)) {
            initData();
        }

        if (StringUtils.isNotBlank(message)) {
            for (String keyWord : keyWords) {
                if (message.contains(keyWord)) {
                    return true;
                }
            }
        }
        return false;
    }

}